import React from 'react';
import '@/assets/public.css'

// npm i immer use-immer -S
import { useImmerReducer } from 'use-immer';

type defaultType = typeof defaultState;
// 两种 action的type类型声明
type ActionType = { type: "UPDATE_NAME", payload: string } | { type: "UPDATE_AGE", payload: number } | { type: "DECARMENT", payload: number } | { type: "RESET", payload: defaultType };

const defaultState = { name: "刘凯欣", age: 18 };

export const ReducerFun: React.FC = () => {
    // 理论铺垫
    // const [state,dispatch] = useReducer(reducer,initState,initAction)
    // initState,初始数据；
    // initAction,处理初始化数据 如果return 就 把值 给state 如果没有 就使用initState
    // dispatch 用于修改数据；执行dispatch 会触发 reducer,reducer 会返回一个新状态
    // reducer 会中在去更新 state

    const initAction = (e: defaultType) => {
        console.log("执行初始化");
        return e
    }


    // 点击button按钮：调用dispatch 会触发 reducer函数；并且返回新值；
    // 在reducer函数的形参中
    // 第一个参数 永远都是上一次的旧状态，第二个参数为 dispatch传递的参数结合
    const reducer = (prevState: defaultType, action: ActionType) => {
        console.log("执行修改");
        //使用useImmerReducer 在case 中只需要在prevState上修改即可，immer内部会复制并返回新对象，因此降低了用户的负担
        switch (action.type) {
            case "UPDATE_NAME":
                prevState.name = action.payload
                break
            case "UPDATE_AGE":
                prevState.age += action.payload
                break
            case "DECARMENT":
                prevState.age -= action.payload
                break
            case "RESET":
                return initAction(defaultState)
            default:
                return defaultState;

        }
    }

    const [state, dispatch] = useImmerReducer(reducer, defaultState, initAction); //由第三个参数，对初始值进行修改后，在赋值给state;


    return (
        <>
            <div>Reducer{JSON.stringify(state)}</div>
            <button onClick={() => {
                dispatch({ type: "UPDATE_NAME", payload: "刘凯欣2" });
            }}>点击修改 state值的名字</button>
            <button onClick={() => {
                dispatch({ type: "UPDATE_AGE", payload: 1 })
            }}>点击修改 state值的年龄</button>
            <div className='flexBox'>
                <SonFun1 {...state} dispatch={dispatch}></SonFun1>
                <SonFun2  {...state} dispatch={dispatch}></SonFun2>
            </div>
        </>
    )
}

export const SonFun1: React.FC<defaultType & { dispatch: React.Dispatch<ActionType> }> = (props) => {
    const { dispatch, ...user } = props;
    return (
        <div className='son_box1'>
            <div>子组件1</div>
            <p>{JSON.stringify(user)}</p>
            <button onClick={() => {
                dispatch({ type: "UPDATE_AGE", payload: 10 })
            }}>修改年龄自增加10</button>
        </div>
    )
}

export const SonFun2: React.FC<defaultType & { dispatch: React.Dispatch<ActionType> }> = (props) => {
    const { dispatch, ...user } = props;
    return (
        <div className='son_box2'>
            <div>子组件2</div>
            <p>{JSON.stringify(user)}</p>
            <button onClick={() => {
                dispatch({ type: "DECARMENT", payload: 5 })
            }}>修改年龄自减去1</button>

            {/* 在子组件中在去调用另外一个子组件，这样还得需要在传一个dispatch 这样有点麻烦； */}
            <RestFun dispatch={dispatch} {...user}></RestFun>
        </div>
    )
}



// 重置组件
// 在重置组件中调用父组件的方法，
export const RestFun: React.FC<defaultType & { dispatch: React.Dispatch<ActionType> }> = (props) => {
    const restFun = () => {
        console.log(props);
        console.log("重置数据")
        props.dispatch({ type: "RESET", payload: defaultState })
    }
    return (
        <>
            <button onClick={restFun}>重置数据</button>
        </>
    )
}